package com.hjq.fcloud.camear;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.hardware.Camera;
import android.os.Handler;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;

import com.hjq.fcloud.R;
import com.hjq.fcloud.other.PermissionCallback;
import com.hjq.fcloud.ui.activity.BaseDetailActivity;
import com.hjq.fcloud.utils.Logger;
import com.hjq.permissions.Permission;
import com.hjq.permissions.XXPermissions;
import com.zhy.adapter.abslistview.CommonAdapter;
import com.zhy.adapter.abslistview.ViewHolder;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * 人脸识别界面基类
 */
public abstract class BaseCameraActivity extends BaseDetailActivity implements SurfaceHolder.Callback, Camera.PreviewCallback {

    public Handler handler = new Handler();
    private Camera mCamera;
    private int cameraId = 0;
    Bitmap bm;
    private int mDisplayRotation;
    private int mDisplayOrientation;
    private int previewWidth;
    private int previewHeight;

    private SurfaceView mView;
    private final CameraErrorCallback mErrorCallback = new CameraErrorCallback();
    private FaceDetectThread detectThread = null;
    private int prevSettingWidth;
    //是否正在处理人脸中，true 正在处理，
    private boolean isHandlerFace;

    @Override
    protected int getLayoutId() {
        return R.layout.activity_camera_viewer;
    }

    @Override
    protected void initView() {
        mView = (SurfaceView) findViewById(R.id.surfaceview);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

        requestCameraPermission();
    }

    @Override
    protected void initData() {
    }


    private void requestCameraPermission() {
        XXPermissions.with(this)
                .permission(Permission.CAMERA, Permission.WRITE_EXTERNAL_STORAGE)
                .request(new PermissionCallback() {
                    @Override
                    public void onGranted(List<String> permissions, boolean all) {
                        SurfaceHolder holder = mView.getHolder();
                        holder.addCallback(BaseCameraActivity.this);
                        holder.setFormat(ImageFormat.NV21);
                    }
                });
    }

    @Override
    protected void onResume() {
        super.onResume();
        startPreview();
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (mCamera != null) {
            mCamera.stopPreview();
        }
    }

    @Override
    public void surfaceCreated(SurfaceHolder surfaceHolder) {
        try {
            Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
            for (int i = 0; i < Camera.getNumberOfCameras(); i++) {
                Camera.getCameraInfo(i, cameraInfo);
                if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
                    if (cameraId == 0) cameraId = i;
                }
            }
            Camera.getCameraInfo(cameraId, cameraInfo);
            if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
                mCamera = Camera.open(cameraId);
            } else {
                showToast("手机没有前置摄像头");
                return;
            }
            mCamera.setPreviewDisplay(mView.getHolder());
        } catch (Exception e) {
            showToast("没有相机权限");
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height) {
        if (surfaceHolder.getSurface() == null || mCamera == null) {
            return;
        }
        Logger.i("surfaceChanged");
        try {
            mCamera.stopPreview();
        } catch (Exception e) {
        }
        configureCamera(width, height);
        setDisplayOrientation();
        setErrorCallback();
        startPreview();
    }

    private void setErrorCallback() {
        mCamera.setErrorCallback(mErrorCallback);
    }

    private void setDisplayOrientation() {
        mDisplayRotation = Util.getDisplayRotation(BaseCameraActivity.this);
        mDisplayOrientation = Util.getDisplayOrientation(mDisplayRotation, cameraId);
        mCamera.setDisplayOrientation(mDisplayOrientation);
    }

    private void configureCamera(int width, int height) {
        Camera.Parameters parameters = mCamera.getParameters();
        setOptimalPreviewSize(parameters, width, height);
        setAutoFocus(parameters);
        mCamera.setParameters(parameters);
    }

    private void setOptimalPreviewSize(Camera.Parameters cameraParameters, int width, int height) {
        List<Camera.Size> previewSizes = cameraParameters.getSupportedPreviewSizes();
        float targetRatio = (float) width / height;
        Camera.Size previewSize = Util.getOptimalPreviewSize(this, previewSizes, targetRatio);
        previewWidth = previewSize.width;
        previewHeight = previewSize.height;
        prevSettingWidth = 1280;
        cameraParameters.setPreviewSize(previewSize.width, previewSize.height);
    }

    private void setAutoFocus(Camera.Parameters cameraParameters) {
        List<String> focusModes = cameraParameters.getSupportedFocusModes();
        if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE))
            cameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
    }

    //开启摄像头 拍摄
    private void startPreview() {
        isHandlerFace = false;
        if (mCamera != null) {
            mCamera.startPreview();
            mCamera.setPreviewCallback(this);
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
        Logger.i("surfaceDestroyed");
        if (mCamera != null) {
            mCamera.setPreviewCallbackWithBuffer(null);
            mCamera.setErrorCallback(null);
            mCamera.release();
            mCamera = null;
        }

    }

    @Override
    public void onPreviewFrame(byte[] _data, Camera _camera) {
        if (!isHandlerFace) {
            isHandlerFace = true;
            waitForFdetThreadComplete();
            detectThread = new FaceDetectThread(handler);
            detectThread.setData(_data);
            detectThread.start();
        }
    }

    private void waitForFdetThreadComplete() {
        if (detectThread == null) {
            return;
        }

        if (detectThread.isAlive()) {
            try {
                detectThread.join();
                detectThread = null;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private class FaceDetectThread extends Thread {
        private Handler handler;
        private byte[] data = null;

        public FaceDetectThread(Handler handler) {
            this.handler = handler;
        }


        public void setData(byte[] data) {
            this.data = data;
        }

        public void run() {
            Bitmap bmp = byteToBmp(data);
            handler.post(() -> handlerBmp(bmp));
        }
    }

    private Bitmap byteToBmp(byte[] data) {
        float aspect = (float) previewHeight / (float) previewWidth;
        int w = prevSettingWidth;
        int h = (int) (prevSettingWidth * aspect);
        Bitmap mBitmap = Bitmap.createBitmap(previewWidth, previewHeight, Bitmap.Config.RGB_565);
        //人脸检测:首先将图像从NV21转换为RGB_565
        YuvImage yuv = new YuvImage(data, ImageFormat.NV21,
                mBitmap.getWidth(), mBitmap.getHeight(), null);
        Rect rectImage = new Rect(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
        ByteArrayOutputStream baout = new ByteArrayOutputStream();
        //图像压缩 得到jpeg数据流
        if (!yuv.compressToJpeg(rectImage, 100, baout)) {
        }
        //bitmapFactory.options 对图片进行解码时的配置参数类
        BitmapFactory.Options bfo = new BitmapFactory.Options();
        //颜色模式
        bfo.inPreferredConfig = Bitmap.Config.RGB_565;
        //解码为Bitmap对象
        mBitmap = BitmapFactory.decodeStream(new ByteArrayInputStream(baout.toByteArray()), null, bfo);
        //从当前存在的位图，按一定的比例创建一个新的位图
        Bitmap mBmp = Bitmap.createScaledBitmap(mBitmap, w, h, false);
        //判断摄像头为前置摄像头
        Camera.CameraInfo info = new Camera.CameraInfo();
        Camera.getCameraInfo(cameraId, info);
        int rotate = mDisplayOrientation;
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT && mDisplayRotation % 180 == 0) {
            if (rotate + 180 > 360) {
                rotate = rotate - 180;
            } else
                rotate = rotate + 180;
        }

        switch (rotate) {
            case 90:
                mBmp = ImageUtils.rotate(mBmp, 90);
                break;
            case 180:
                mBmp = ImageUtils.rotate(mBmp, 180);
                break;
            case 270:
                mBmp = ImageUtils.rotate(mBmp, 270);
                break;
        }
        return mBmp;
    }

    private void handlerBmp(Bitmap bmp) {
        Matrix matrix = new Matrix();
        matrix.setScale(0.65f, 0.65f);
        bm = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true);

        handlerResultBmp(bm);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        handler.removeCallbacksAndMessages(null);
    }

    /**
     * 继续人脸识别
     */
    public void continueScan(){
        isHandlerFace = false;
    }

    /**
     * 人脸比对
     *
     * @param bm
     */
    protected abstract void handlerResultBmp(Bitmap bm);

}

